package com.siyoumi.component.auth_img.impl;

import com.siyoumi.component.XRedis;
import com.siyoumi.component.auth_img.AuthImgService;
import com.siyoumi.component.auth_img.entity.AuthImgData;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.component.XApp;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import lombok.Data;
import lombok.experimental.Helper;
import lombok.extern.slf4j.Slf4j;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.List;

@Data
@Slf4j
public class CodeAuthImgServiceImpl extends AuthImgService {
    public static CodeAuthImgServiceImpl getIns(String key) {
        CodeAuthImgServiceImpl app = new CodeAuthImgServiceImpl();
        app.setRedisKey(key);

        return app;
    }

    Integer fontSize = 30;
    Integer width;
    Integer height;

    @Override
    public List<BufferedImage> getImgInfo(AuthImgData data) {
        if (XStr.isNullOrEmpty(data.getCode())) {
            data.setCode(XApp.random(1000, 9999) + "");
        }

        BufferedImage img = createAuthCode(data.getCode());
        setRedisVal(data.getCode());
        return List.of(img);
    }

    @Override
    public XReturn auth(AuthImgData data) {
        log.debug("key: {}", getRedisKey());
        String v = XRedis.getBean().getAndDel(getRedisKey());
        if (XStr.isNullOrEmpty(v)) {
            return EnumSys.ADMIN_AUTH_IMG_ERR.getR();
        }

        boolean isOK = v.equals(data.getCode());
        if (isOK) {
            return EnumSys.OK.getR("验证成功");
        }

        return EnumSys.ADMIN_AUTH_IMG_ERR.getR();
    }

    private BufferedImage createAuthCode(String vcode) {
        Integer codeLen = vcode.length();//验证码长度
        Integer fontSize = getFontSize();//字体大小
        //根据文本长度动态计算长和宽
        double widthFinal = fontSize * codeLen * 1.5 + (double) fontSize / 2;
        int width = (int) widthFinal;
        int height = fontSize * 2;
        setWidth(width);
        setHeight(height);
        log.debug("width: {}", width);
        log.debug("height: {}", height);
        //创建图片
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = image.createGraphics();
        g.setColor(Color.WHITE);//设置背景色
        g.fillRect(0, 0, width, height);//填充背景
//        g.setColor(Color.LIGHT_GRAY);//设置边框颜色

        log.debug("添加干扰");
        addNoise(g);
        log.debug("绘验证码: {}", vcode);
        addAuthCode(g, vcode);
        g.dispose();

        return image;
    }

    /**
     * 添加干扰
     */
    private void addNoise(Graphics2D g) {
        String noise_list = "2345678abcdefhijkmnpqrstuvwxyz";
        String[] noise_arr = noise_list.split("");

        Font font = new Font("Arial", Font.ITALIC, 10);
        for (int i = 0; i < 10; i++) {
            g.setColor(new Color(XApp.random(150, 225), XApp.random(150, 225), XApp.random(150, 225)));
            for (int j = 0; j < 5; j++) {
                String s = noise_arr[XApp.random(0, 29)];
                addString(g, s, XApp.random(0, getWidth()), XApp.random(0, getHeight()), font);
            }
        }
    }

    private void addAuthCode(Graphics2D g, String vcode) {
        String[] vcode_arr = vcode.split("");

        g.setColor(new Color(XApp.random(1, 150), XApp.random(1, 150), XApp.random(1, 150)));

        Integer font_size = getFontSize();
        Font font = new Font("宋体", Font.BOLD, font_size + 15);
        double x = 0.0;
        double y = 0.0;
        for (int i = 0; i < vcode_arr.length; i++) {
            String s = vcode_arr[i];
            y = font_size * (XApp.random(10, 20) / 10.0);
            x += font_size * (XApp.random(12, 14) / 10.0);
            log.debug("x: {}", x);
            log.debug("y: {}", y);
            //旋转
            int rnd = XApp.random(-50, 50);
            log.debug("rnd: {}", rnd);
            g.rotate(Math.toRadians(rnd), x, y);
            addString(g, s, (int) x, (int) y, font);
            g.rotate(Math.toRadians(-rnd), x, y);
        }
    }

    /**
     * 添加文本
     *
     * @param g
     * @param str
     * @param x
     * @param y
     * @param font
     */
    public void addString(Graphics2D g, String str, Integer x, Integer y, Font font) {
        if (font != null) {
            g.setFont(font);
        }
        g.drawString(str, x, y);
    }
}
